public class UT_SP_Trigger{
    static testMethod void testSPTriggerForMultiAccountSP_NormalCase(){
        Support_Program__c spABC = new Support_Program__c( RecordTypeId=RT.MASPId, Name='UnitTestSPABC', Account__c=null, Contract__c=null, Apply_To_All_Contacts_In_Account__c=True  );
        Support_Program__c spD = new Support_Program__c( RecordTypeId=RT.MASPId, Name='UnitTestSPD', Account__c=null, Contract__c=null, Apply_To_All_Contacts_In_Account__c=True  );
        insert spABC; insert spD;
        
        Account a = new Account(Name='UnitTestA',Support_Program__c=spABC.id);
        Account b = new Account(Name='UnitTestB',Support_Program__c=spABC.id);
        Account c = new Account(Name='UnitTestA',Support_Program__c=spABC.id);
        Account d = new Account(Name='UnitTestB',Support_Program__c=spD.id);
        Account accNoSP = new Account(Name='UnitTestA',Support_Program__c=null);
                        
        AssertSPInvariants( spABC.Id,true,0 );
        AssertSPInvariants( spD.Id,true,0 );              
        
        spABC.Apply_To_All_Contacts_In_Account__c = !spABC.Apply_To_All_Contacts_In_Account__c;
        spD.Apply_To_All_Contacts_In_Account__c = !spD.Apply_To_All_Contacts_In_Account__c;        
        Support_Program__c[] spUpdateSet = new List<Support_Program__c>{ spABC,spD };
        update spUpdateSet;  
        
        AssertSPInvariants( spABC.Id,true,0 );
        AssertSPInvariants( spD.Id,true,0 );              
    }

    // Just assert that it doesn't throw and that these objects follow the invariants
    static testMethod void testSPTriggerForNamedCallerSP_NormalCase(){
        UT_SObjectFactory.InterconnectedSObjectsForContact conrel = new UT_SObjectFactory.InterconnectedSObjectsForContact();
        UT_SObjectFactory.InterconnectedSObjectsForContact conrel2 = new UT_SObjectFactory.InterconnectedSObjectsForContact();
        
        AssertSPInvariants( conrel.sp.Id,false,1 );
        AssertSPInvariants( conrel2.sp.Id,false,1 );
        
        conrel.sp.Apply_To_All_Contacts_In_Account__c = True;
        conrel2.sp.Apply_To_All_Contacts_In_Account__c = False;
        
        Support_Program__c[] spUpdateSet = new List<Support_Program__c>{ conrel.sp, conrel2.sp };
        update spUpdateSet;
        
        AssertSPInvariants( conrel.sp.Id,false,1 );
        AssertSPInvariants( conrel2.sp.Id,false,1 );        
    }
    
//
// Note, once these are working and the Account validation rule is fixed, we should have much stronger enforcement of the data model.
//
    
    public static void AssertSPInvariants(ID spId, Boolean ExpectMultiSP, Integer ExpectingEntitlementsCount) {
/*        String strRtName =  (ExpectMultiSP) ? 'Multi-Account Support Program' : 'Contract Support Program';
        Program_Asset__c[] pa = [select Id,Asset__r.Name,Support_Program__r.Id From Program_Asset__c];
        for(Program_Asset__c x:pa){
            system.debug('>>> ASSET='+x.Asset__r);
        }
        
        Support_Program__c sp = [Select Id,Name,RecordType.Name,RecordType.Id,Account__c,Account__r.Name,
            Apply_To_All_Contacts_In_Account__c,
            (Select Id,Name,Business_Hours__c From Entitlements__r) ,
            (Select Id,Name,Contact__c From Program_Contacts__r),
            (Select Id,Name,Asset__c    From Program_Assets__r),
            (Select Id,Name    From Accounts__r),
            P1__c
            From Support_Program__c Where Id=:spId Limit 1];
        system.assertEquals(spId,sp.id,'Just warming up.  If this one fails, we\'ve got bigger problems...');
        system.assertEquals(strRtName,sp.RecordType.Name,'For SP '+sp.Name+' with Account='+sp.Account__r.Name+',P1='+sp.P1__c+':  ');
        system.assertEquals(sp.Entitlements__r.size(),ExpectingEntitlementsCount,'Expected '+ExpectingEntitlementsCount+' child entitlements'); 
        
        
        if (ExpectMultiSP) {
            AssertSPInvariantForMultiAccountSP(sp);
        } else {
            AssertSPInvariantForNamedCallerSP(sp);
        }
*/
    }
       
    //
    // Test the invariants for the MultiAccountSP RT (can't have ProgramContact children, no ProgramAssets, etc.)
    //

/*
    public static void AssertSPInvariantForMultiAccountSP(Support_Program__c sp) {
            system.assertEquals(sp.Program_Contacts__r.size(),0,'Multi-Account SPs cannot have an Asset relationships.  That concept is only supported in the other record type.');               
            system.assertEquals(sp.Program_Assets__r.size(),0,'Multi-Account SPs cannot have Contact relationships through PC linkers.  They can only have implicit related Contacts through their related Accounts.  The other record type supports PC linkages.');           
            system.assertEquals(sp.Account__c,null,'Multi-Account SPs can never use the SP.Account field; it must be null.  To link them to accounts, you populate the lookup Account.SupportProgram and point it to the SP.');           
    }
    public static void AssertSPInvariantForNamedCallerSP(Support_Program__c sp) {
            system.assertEquals(sp.Program_Contacts__r.size(),0,'NCSPs can have zero or more related Assets.');
            system.assertEquals(sp.Program_Contacts__r.size(),0,'NCSPs can have zero or more related Contacts.');                              
            system.assertNotEquals(sp.Account__c,null,'NCSPs MUST use the SP.Account field; it cannot be null.'); 

            system.assertEquals(sp.Accounts__r.size(),0,'NCSPs can never be reference by any Account\'s Account.Support_Program__c field.  NCSPs are always account-specific.');                       
    }
*/        
    static testMethod void testSPTriggerForNamedCallerSP(){
        UT_SObjectFactory.InterconnectedSObjectsForContact conrel = new UT_SObjectFactory.InterconnectedSObjectsForContact();
        UT_SObjectFactory.InterconnectedSObjectsForContact conrel2 = new UT_SObjectFactory.InterconnectedSObjectsForContact();
        
        AssertSPInvariants( conrel.sp.Id,false,1 );
        AssertSPInvariants( conrel2.sp.Id,false,1 );        
        
        
        conrel.sp.Apply_To_All_Contacts_In_Account__c = True;
        conrel2.sp.Apply_To_All_Contacts_In_Account__c = False;

               
        Support_Program__c[] spUpdateSet = new List<Support_Program__c>{ conrel.sp, conrel2.sp };
        update spUpdateSet;
        
        AssertSPInvariants( conrel.sp.Id,false,1 );
        AssertSPInvariants( conrel2.sp.Id,false,1 );                
    }
    
    static testMethod void testSPTrigger_ShouldFailNCSP() 
    {
        UT_SObjectFactory.InterconnectedSObjectsForNCSP o = 
            new UT_SObjectFactory.InterconnectedSObjectsForNCSP(false,5);
        Support_Program__c spBad = o.sp.clone(false,true);
        spBad.Account__c = null;    
        try { insert spBad; } catch(Exception e) { return; }
        system.assert(false,'Should have thrown for null acct');
    } 
    
}